【前言】
這兩天的文章都是 web3.js 的學習筆記,大部分內容都來自他們的官方文件!之後還會有 ethers.js 的學習筆記。然後延伸探討到底要使用什麼方法來取得 Token Owner 以及 Account Balance 比較好。不過看了越多官方文件就越痛苦,更不用說還要實作…
【web3.js】
we3.js 是一個 JavaScript 的套裝 library,裡面擁有許多函數或介面可以讓開發者利用 HTTP, IPC 或 WebSocket 遠端連動以太坊上的節點,進而取得鏈上訊息、合約資料、帳戶資訊。甚至是在取得使用者登入簽名後進行交易動作。
下載套件:
npm install web3
yarn add web3
we3.js 的四個重要模組:
web3-eth
用於以太坊的區塊鏈以及智能合約。web3-shh
用於 **Whisper 通訊協議(Ehtereum’s inter-application communication protocol)**和 在 P2P 對等式網路中連動或播送。web3-bzz
用於 Swarm 記帳協議(Swarm Accounting Protocol,SWAP)和去中心化的資料儲存。web3-utils
提供 Dapp 開發者可能會需要用到的功能函數。因為篇幅有限所以我這幾天介紹 web3.js 的文章重點會放在 web3-eth
以及 web3-utils
,如果明年我還有參加鐵人賽也許會更加詳細的介紹這些模組!
如果在支援 MetaMask 的瀏覽器中有下載 MetaMask,便可以透過 EIP-1193: Ethereum Provider JavaScript API 這項協定來利用 window.ethereum
來達到同樣目的!這也是為什麼在我之前【連動 MetaMask】的系列文章之中有透過這個方法得到登入者資料過。
EIP-1193: Ethereum Provider JavaScript API
利用以下的程式碼中的 givenProvider
測試是不是已經取得以太坊連動!如果變數 web3
回傳 null
的話表示還沒連上。
// In Node.js use: const Web3 = require('web3');
const web3 = new Web3(Web3.givenProvider || "ws://localhost:8545");
【we3.eth】web3-eth
是一個用於以太坊的區塊鏈以及智能合約的模組,我們在取得連動之後就可以透過 getAccounts
取得當前節點的地址資料。
const Web3 = require('web3'); // In Node.js
web3.eth.getAccounts(console.log);
> ["0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe" ,"0x85F43D8a49eeB85d32Cf465507DD71d507100C1d"]
要注意的是透過 we3.js 回傳的所有地址資料都是核對和地址(checksum addresses),也就是說裡面可能包含一些大寫字母以及一些小寫字母。如果想要規避錯誤檢測的話可以把整個字串轉為小寫。之前【連動 MetaMask】的系列文章之中有提到過這篇文章!
How can I check if an Ethereum address is valid?
【we3.eth.accounts】web3.eth.accounts
做為以太坊帳戶的變數型態,可以來核准交易或傳遞資料。
var Accounts = require('web3-eth-accounts');
// Passing in the eth or web3 package is necessary to allow retrieving chainId, gasPrice and nonce automatically
// for accounts.signTransaction().
var accounts = new Accounts('ws://localhost:8546');
web3.eth.accounts.create([entropy])
可以產生一個以太坊帳戶的物件。
web3.eth.accounts.create([entropy]); // Generates an account object with private key and public key.
// example
web3.eth.accounts.create(web3.utils.randomHex(32));
> {
address: "0xe78150FaCD36E8EB00291e251424a0515AA1FF05",
privateKey: "0xcc505ee6067fba3f6fc2050643379e190e087aeffe5d958ab9f2f3ed3800fa4e",
signTransaction: function(tx){...},
sign: function(data){...},
encrypt: function(password){...}
}
Parameters:entropy
- String
(optional): 可以使用任意字串來增加亂度,想要使用這個參數的話至少要提供 32 個字元的字串。如果沒有的話會自動使用 randomhex()
產生隨意字串。
Returns:Object
- 此以太坊帳戶物件會包含以下資料結構:
address
- string
: 以太坊帳號地址。privateKey
- string
: 帳號私鑰。為了安全問題,私鑰永遠不可以被分享或儲存在未加密過的儲存空間,並且在使用後需要確保這個值是 null
的。
signTransaction(tx [, callback])
- Function
: 此函數用於簽核交易,詳細可見 web3.eth.accounts.signTransaction()
。sign(data)
- Function
: 此函數用於簽核交易,詳細可見 web3.eth.accounts.signTransaction()
。web3.eth.accounts.wallet
此變數型態可包含已記錄的多個以太坊帳戶資料,這些帳戶可以被用在 web3.eth.accounts.signTransaction()
。
web3.eth.accounts.wallet;
> Wallet {
0: {...}, // account by index
"0xF0109fC8DF283027b6285cc889F5aA624EaC1F55": {...}, // same account by address
"0xf0109fc8df283027b6285cc889f5aa624eac1f55": {...}, // same account by address lowercase
1: {...},
"0xD0122fC8DF283027b6285cc889F5aA624EaC1d23": {...},
"0xd0122fc8df283027b6285cc889f5aa624eac1d23": {...},
add: function(){},
// Adds an account using a private key or account object to the wallet.
// Return The added account(object)
remove: function(){},
// Removes an account from the wallet.
// Return a Boolean(true if the wallet was removed)
save: function(){},
// Stores the wallet encrypted and as string in local storage.
// Return a Boolean
load: function(){},
// Loads a wallet from local storage and decrypts it.
// Return The wallet(object)
clear: function(){},
// Securely empties the wallet and removes all its accounts.
// Return The wallet(object)
length: 2,
}
【we3.eth.personal】web3-eth-personal
這個套件可以讓開發者與以太坊節點的帳戶連動,節點的決定由 provider
提供。要注意的是這個套件裡面的函數會回傳許多敏感資訊像是密碼或者私鑰!
// or using the web3 umbrella package
var Web3 = require('web3');
var web3 = new Web3(Web3.givenProvider || 'ws://some.local-or-remote.node:8546');
// -> web3.eth.personal
// Warning!! Never call these functions over a unsecured Websocket or HTTP provider, as your password will be sent in plain text!
我們可以利用 setProvider
來設定當前想要的 provider
。
// Example: Local Geth Node
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
// Example: Remote Node Provider
var web3 = new Web3("https://eth-mainnet.alchemyapi.io/v2/your-api-key");
provider
其實就是 we3 如何與區塊鏈聯繫,也就是一個具有訪問以及連動區塊鏈的能力的節點。其會使用一個 JSON-RPC requests
並且回傳一個 response
。通常會被遞交一個 request
給 HTTP 或 IPC socket based server。
web3.eth.personal.sign
此函數可產出 Ethereum 特定的 signature
。
web3.eth.personal.sign(dataToSign, address, password [, callback])sign
// Warning!! Sending your account password over an unsecured HTTP RPC connection is highly unsecure.
// example
web3.eth.personal.sign(web3.utils.utf8ToHex("Hello world"), "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe", "test password!")
.then(console.log);
> "0x30755ed65396facf86c53e6217c52b4daebe72aa4941d89635409de4c9c7f9466d4e9aaec7977f05e923889b33c0d0dd27d7226b6e6f56ce737465c5cfd04be400"
Parameters:
String
- Data to sign. If String it will be converted using web3.utils.utf8ToHex.String
- Address to sign data with.String
- The password of the account to sign data with.Function
- (optional) Optional callback, returns an error object as first parameter and the result as second.Promise
returns String
- The signature.web3.eth.personal.getAccounts
會回傳一個此節點控制的地址們的陣列。利用 provider
和 calling RPC method personal_listAccounts
。使用 web3.eth.accounts.create()
不會在這個 list 裡面增加帳號。需要使用 web3.eth.personal.newAccount()
才能達到在 list 裡面增加帳號的效果。
web3.eth.personal.getAccounts([callback])
// example
web3.eth.personal.getAccounts()
.then(console.log);
> ["0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe", "0xDCc6960376d6C6dEa93647383FfB245CfCed97Cf"]
此函數和 web3.eth.getAccounts()
的結果是一樣的,除非是 calls RPC method eth_accounts。
Returns:Promise<Array>
- 一個此節點控制的地址們組成的陣列。
【小結】
今天就簡單介紹了幾個 we3.eth.accounts
以及 we3.eth.personal
的相關函數和基本資訊,明天會接續介紹 we3.eth.contract
和 web3.utis
這兩個套件!
【參考資料】
web3.js - Ethereum JavaScript API - web3.js 1.0.0 documentation